package com.example.cacheservice.controller;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.cacheservice.common.entity.User;
import com.example.cacheservice.dao.UserMapper;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.util.List;

/**
 * @author wuxinxin
 */
@RestController
public class GuavaController{

    private static int size = 1000;

    private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);

    private static String PREFIX="guava:";

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 存在Bloom,那么获取数据
     * @param id
     * @return
     */
    @RequestMapping("/guava/bloom/get/{id}")
    @GetMapping
    public User guavaBloomTestGet(@PathVariable Integer id){

        //判断布隆过滤器是否存在
        if(bloomFilter.mightContain(id)){

            //获取缓存数据
            String s = stringRedisTemplate.opsForValue().get(PREFIX+id.toString());

            if(s==null){
                //缓存不存在，查询数据库
                User user = userMapper.selectById(id);
                //空值处理（布隆误判 | 数据被删）
                String value=user==null?"":JSONUtil.toJsonStr(user);
                //加入缓存
                stringRedisTemplate.opsForValue().set(PREFIX+id.toString(), value, Duration.ofSeconds(300L));
                return user;
            }else if(s.equals("")){
                //缓存空值处理
                return null;
            }else {

                return JSONUtil.toBean(s,User.class);
            }

        }

        //不存在布隆过滤器直接返回
        return null;
    }


    /**
     * 添加数据更新Bloom
     * @param user
     * @return
     */
    @RequestMapping("/guava/bloom/set")
    @GetMapping
    public String guavaBloomTestSet(@RequestBody User user){
        //插入数据
        userMapper.insert(user);
        //加到布隆过滤器
        bloomFilter.put(user.getId());

        return "success";
    }

    /**
     * 数据预热Bloom
     */
    @EventListener(ContextRefreshedEvent.class)
    public void readyBloom(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("id");
        List<User> users = userMapper.selectList(userQueryWrapper);
        for (User user:users){
            bloomFilter.put(user.getId());
        }
    }
}
